"""
题目 2：线程同步 - 餐厅点餐系统（30 分）
模拟餐厅点餐系统的多线程场景，要求：
创建一个餐厅类Restaurant，包含：
菜单menu（字典，如{"汉堡": 25, "薯条": 15}）。
订单队列orders（最多容纳 20 个订单）。
已完成订单completed_orders。
创建 3 个厨师线程：
每个厨师从orders队列取出订单，处理耗时随机（1-3 秒）。
处理完成后将订单添加到completed_orders。
创建 5 个顾客线程：
每个顾客随机点 1-3 个菜（从菜单中选择），订单格式为{"顾客ID": 1, "菜品": ["汉堡", "薯条"]}。
使用适当的线程同步机制（如锁、信号量）确保线程安全。
主程序运行 5 秒后停止所有线程，输出已完成订单数量。
评分标准
项目	分值	评分标准
餐厅类设计	6 分	正确实现餐厅类，包含菜单、订单队列和完成订单列表
线程创建与任务分配	6 分	创建 3 个厨师线程和 5 个顾客线程，正确分配任务
线程同步机制	12 分	使用threading.Lock和threading.Semaphore确保线程安全，无竞态条件
定时控制与结果输出	4 分	主程序运行 5 秒后停止所有线程，正确输出已完成订单数量
代码健壮性	2 分	处理订单队列为空或已满的情况
"""
import threading
import time
import random
class Restaurant:
    def __init__(self):
        self.menu = {"汉堡": 25, "薯条": 15, "可乐": 8, "炸鸡": 30, "沙拉": 20}
        self.orders = []
        self.completed_orders = []
        self.lock = threading.Lock()
        self.order_semaphore = threading.Semaphore(20)  # 最多20个订单

    def cook_order(self, cook_id):
        while True:
            if not self.orders:
                time.sleep(0.1)
                continue
            with self.lock:
                if not self.orders:
                    continue
                order = self.orders.pop(0)
            time.sleep(random.uniform(1, 3))  # 模拟烹饪时间
            with self.lock:
                self.completed_orders.append(order)
                print(f"厨师 {cook_id} 完成订单: {order}")

    def customer_order(self, customer_id):
        while True:
            self.order_semaphore.acquire()  # 等待空位
            with self.lock:
                order = {
                    "customer_id": customer_id,
                    "dishes": random.sample(list(self.menu.keys()), random.randint(1, 3))
                }
                self.orders.append(order)
                print(f"顾客 {customer_id} 下单: {order}")
            time.sleep(random.uniform(0.5, 1))  # 模拟顾客思考时间


if __name__ == "__main__":
    restaurant = Restaurant()
    cooks = [threading.Thread(target=restaurant.cook_order, args=(i,)) for i in range(1, 4)]
    customers = [threading.Thread(target=restaurant.customer_order, args=(i,)) for i in range(1, 6)]

    for t in cooks + customers:
        t.daemon = True
        t.start()

    time.sleep(5)  # 运行5秒
    with restaurant.lock:
        print(f"已完成订单数量: {len(restaurant.completed_orders)}")
